package com.wontube.smr.dao.bo;

import java.util.Calendar;
import java.util.List;

import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;

import com.wontube.client.extension.utils.StringUtils;
import com.wontube.client.modle.vo.PagenateInfo;
import com.wontube.core.dao.mybatis.Criteria;
import com.wontube.core.dao.mybatis.QueryExample;
import com.wontube.smr.bo.constants.SiteConstants;
import com.wontube.smr.client.model.po.Movie;
import com.wontube.smr.client.model.vo.MovieItems;
import com.wontube.smr.dao.mapper.MovieMapper;
import com.wontube.smr.pub.DefaultDBHelper;
import com.wontube.smr.web.client.model.bo.QueryItemParams;

/**
 * @author yuechao
 * 
 */
public final class MovieSelectDao {
	private MovieSelectDao() {
	}

	public static MovieItems selectRelatedMusics(String movieId, PagenateInfo pageInfo) {
		Movie movie = getMovie(movieId);
		if (movie == null || StringUtils.isNullOrEmpty(movie.getActors())) {
			return new MovieItems();
		}

		QueryExample ex = new QueryExample();
		ex.or().addCriterion("movie.actors = ", movie.getActors())
				.addCriterion("movie.movie_type = ", Movie.TYPE_MUSIC);
		ex.setOrderByClause("movie.sort_index asc");
	
		return selectByExample(ex, pageInfo);	
	}

	public static MovieItems selectVevoMusicsByArtist(String artist, PagenateInfo pageInfo) {
		QueryExample ex = new QueryExample();
		ex.or().addCriterion("movie.movie_type=", Movie.TYPE_MUSIC)
				.addCriterion("movie.website=", SiteConstants.WEBSITE_VEVO)
				.addCriterion("movie.actors=", artist);
		ex.setOrderByClause("movie.sort_index asc");		
		
		return selectByExample(ex, pageInfo);		
	}

	public static MovieItems selectMusics(PagenateInfo pageInfo) {
		return selectMusics(null, pageInfo);
	}

	public static MovieItems selectMusics(String genreName, PagenateInfo pageInfo) {
		return selectMusics(genreName, null, pageInfo);
	}

	public static MovieItems selectMusics(String genreName, String initial, PagenateInfo pageInfo) {
		return selectOrderby(null, Movie.TYPE_MUSIC, genreName, initial, pageInfo, "movie.sort_index asc");
	}
	
	public static MovieItems selectRecentMusic(QueryItemParams params, PagenateInfo pageInfo) {
		return selectRecentMusics(params.getGenre(), params.getInitial(), pageInfo);
	}

	public static MovieItems selectRecentMusics(String genreName, PagenateInfo pageInfo) {
		return selectRecentMusics(genreName, null, pageInfo);
	}

	public static MovieItems selectRecentMusics(String genreName, String initial, PagenateInfo pageInfo) {
		return selectWithRecent(null, Movie.TYPE_MUSIC, genreName, initial, pageInfo);
	}

	public static Movie getMovie(String movieId) {
		SqlSession session = DefaultDBHelper.getSqlSession(true);
		try {
			MovieMapper movieMapper = session.getMapper(MovieMapper.class);
			return movieMapper.selectByPrimaryKey(movieId);
		} finally {
			session.close();
		}
	}
	
	public static MovieItems search(String query, String movieType, PagenateInfo pageInfo) {		
		return search(query, movieType, null, pageInfo);
	}

	public static MovieItems search(String query, String movieType, String website, PagenateInfo pageInfo) {		
		QueryExample ex = new QueryExample();
		StringBuilder sb = new StringBuilder();
		query = query.replaceAll("[']", "''");
		sb.append("(movie.title ilike '%" + query + "%'");
		sb.append(" or movie.actors ilike '%" + query + "%'");
		sb.append(" or movie.director ilike '%" + query + "%')");
		ex.or().addCriterion("movie.movie_type = ", movieType)
				 .addCriterion("movie.website=", website)
				 .addCriterion(sb.toString());
		ex.setOrderByClause("movie.sort_index asc");

		return selectByExample(ex, pageInfo);		
	}
	
	public static int getMovieCount(String query, String movieType){
		return getMovieCount(query, movieType, null);
	}

	public static int getMovieCount(String query, String movieType, String website) {
		QueryExample ex = new QueryExample();

		StringBuilder sb = new StringBuilder();
		query = query.replaceAll("[']", "''");
		sb.append("(movie.title ilike '%" + query + "%'");
		sb.append(" or movie.actors ilike '%" + query + "%'");
		sb.append(" or movie.director ilike '%" + query + "%')");
		ex.or().addCriterion("movie.movie_type = ", movieType)
				.addCriterion("movie.website=", website)
				.addCriterion(sb.toString());

		return getMovieCount(ex);
	}

	private static int getMovieCount(QueryExample ex) {
		SqlSession session = DefaultDBHelper.getSqlSession(true);
		try {
			MovieMapper movieMapper = session.getMapper(MovieMapper.class);
			int count = movieMapper.countByExample(ex);
			return count;
		} finally {
			session.close();
		}
	}

	public static MovieItems selectHuluWeekPopular(PagenateInfo pageInfo) {
		return selectWeekPopular(SiteConstants.WEBSITE_HULU, Movie.TYPE_MOVIE, pageInfo);
	}

	public static MovieItems selectWeekPopular(String website, String movieType, PagenateInfo pageInfo) {
		MovieItems items = new MovieItems(pageInfo);

		QueryExample ex = new QueryExample();
		ex.or().addCriterion("movie.website = ", website).addCriterion("movie.movie_type = ", movieType);
		ex.setOrderByClause("movie_week.sort_index asc");
		RowBounds rowBounds = new RowBounds(pageInfo.getOffset(), pageInfo.getLimit());

		SqlSession session = DefaultDBHelper.getSqlSession(true);
		try {
			MovieMapper movieMapper = session.getMapper(MovieMapper.class);
			List<Movie> movies = movieMapper.selectWithWeek(ex, rowBounds);
			int count = movieMapper.countWithWeek(ex);
			items.setTotalCount(count);

			items.setItems(movies);
		} finally {
			session.close();
		}

		return items;
	}

	public static MovieItems selectHuluRecentMovies(String genreName, PagenateInfo pageInfo) {
		return selectWithRecent(SiteConstants.WEBSITE_HULU, Movie.TYPE_MOVIE, genreName, null, pageInfo);
	}

	public static MovieItems selectHuluPopularMovies(PagenateInfo pageInfo) {
		return selectOrderby(SiteConstants.WEBSITE_HULU, Movie.TYPE_MOVIE, null, null, pageInfo, "movie.sort_index asc");
	}

	public static MovieItems selectHuluTopRatedMovies(String genreName, PagenateInfo pageInfo) {
		return selectOrderby(SiteConstants.WEBSITE_HULU, Movie.TYPE_MOVIE, genreName, null, pageInfo,
				"movie.score desc");
	}

	public static MovieItems selectHuluPopularMovies(String genreName, PagenateInfo pageInfo) {
		return selectOrderby(SiteConstants.WEBSITE_HULU, Movie.TYPE_MOVIE, genreName, null, pageInfo,
				"movie.sort_index asc");
	}

	private static MovieItems selectOrderby(String website, String movieType, String genreName, String initial,
			PagenateInfo pageInfo, String orderBy) {
		QueryExample ex = new QueryExample();
		ex.or().addCriterion("movie.website = ", website).addCriterion("movie.movie_type = ", movieType)
				.addCriterion("movie.title_initial=", initial);
		ex.setOrderByClause(orderBy);		
		return selectByExample(ex, genreName, pageInfo);		
	}

	private static MovieItems selectWithRecent(String website, String movieType, String genreName, String initial,
			PagenateInfo pageInfo) {
		MovieItems items = new MovieItems(pageInfo);
		QueryExample ex = new QueryExample();
		ex.or().addCriterion("movie.website = ", website).addCriterion("movie.movie_type = ", movieType)
				.addCriterion("movie.title_initial=", initial);
		ex.setOrderByClause("recent_movie.sort_index asc, recent_movie.version desc");
		RowBounds rowBounds = new RowBounds(pageInfo.getOffset(), pageInfo.getLimit());

		SqlSession session = DefaultDBHelper.getSqlSession(true);
		try {
			MovieMapper movieMapper = session.getMapper(MovieMapper.class);
			if (StringUtils.isNullOrEmpty(genreName)) {
				List<Movie> movies = movieMapper.selectWithRecent(ex, rowBounds);
				items.setItems(movies);
				int count = movieMapper.countWithRecent(ex);
				items.setTotalCount(count);
			} else {
				List<Movie> movies = movieMapper.selectWithRecentByGenre(genreName, ex, rowBounds);
				items.setItems(movies);
				int count = movieMapper.countWithRecentByGenre(genreName, ex);
				items.setTotalCount(count);
			}
		} finally {
			session.close();
		}

		return items;
	}

	public static MovieItems selectHuluMovies(QueryItemParams params, PagenateInfo pageInfo) {
		return selectMovies(SiteConstants.WEBSITE_HULU, Movie.TYPE_MOVIE, params, pageInfo);
	}

	public static MovieItems selectMovieTraillers(String genreName, PagenateInfo pageInfo) {
		QueryItemParams params = new QueryItemParams();
		params.setGenre(genreName);
		return selectMovieTraillers(params, pageInfo);
	}

	public static MovieItems selectMovieTraillers(QueryItemParams params, PagenateInfo pageInfo) {
		return selectMovies(null, Movie.TYPE_TRAILER, params, pageInfo);
	}

	public static MovieItems selectMovieImdbTraillers(QueryItemParams params, PagenateInfo pageInfo) {
		return selectMovies(SiteConstants.WEBSITE_IMDB, Movie.TYPE_TRAILER, params, pageInfo);
	}
	
	public static MovieItems selectMovieYoutbeMusic(QueryItemParams params, PagenateInfo pageInfo) {
		return selectMovies(SiteConstants.WEBSITE_YOUTUBE, Movie.TYPE_MUSIC, params, pageInfo);
	}

	public static MovieItems selectYoutubeMovie(QueryItemParams params, PagenateInfo pageInfo) {
		return selectMovies(SiteConstants.WEBSITE_YOUTUBE, Movie.TYPE_MOVIE, params, pageInfo);
	}

	public static MovieItems selectVevoMusics(QueryItemParams params, PagenateInfo pageInfo) {
		return selectMovies(SiteConstants.WEBSITE_VEVO, Movie.TYPE_MUSIC, params, pageInfo);
	}

	private static MovieItems selectMovies(String website, String movieType, QueryItemParams params,
			PagenateInfo pageInfo) {		
		QueryExample ex = new QueryExample();
		Criteria cri = ex.or();
		cri.addCriterion("movie.website=", website).addCriterion("movie.title_initial=", params.getInitial())
				.addCriterion("movie.movie_type=", movieType);

		Integer decade = params.getDecade();
		if (decade != null) {
			Calendar calendar = Calendar.getInstance();
			calendar.clear();
			calendar.set(decade, 0, 1);
			cri.addCriterion("movie.publish_time >=", calendar.getTime());
			calendar.set(decade + 10, 0, 1);
			cri.addCriterion("movie.publish_time <", calendar.getTime());
		}

		if ("time".equals(params.getSort())) {
			ex.setOrderByClause("movie.publish_time desc NULLS LAST, movie.sort_index asc, movie.score desc");
		} else {
			ex.setOrderByClause("movie.sort_index asc");
		}

		ex.setDistinct(true);
		return selectByExample(ex, params.getGenre(), pageInfo);		
	}

	public static MovieItems selectMoviefoneTrailler(int year, int month, PagenateInfo pageInfo) {		
		QueryExample ex = new QueryExample();
		Criteria cri = ex.or();
		cri.addCriterion("movie.website=", SiteConstants.WEBSITE_MOVIEFONE);
		cri.addCriterion("movie.movie_type=", Movie.TYPE_TRAILER);
		Calendar cal = Calendar.getInstance();
		cal.clear();
		cal.set(year, month - 1, 1);
		cri.addCriterion("movie.publish_time >=", cal.getTime());
		cal.set(year, month, 1);
		cri.addCriterion("movie.publish_time <", cal.getTime());

		return selectByExample(ex, pageInfo);
	}

	public static MovieItems selectComingSoonTrailers(String genreName, PagenateInfo pageInfo) {		
		Calendar calendar = Calendar.getInstance();
		QueryExample ex = new QueryExample();
		ex.or().addCriterion("movie.website=", SiteConstants.WEBSITE_MOVIEFONE)
				.addCriterion("movie.publish_time > ", calendar.getTime());
		ex.setOrderByClause("movie.publish_time asc, movie.sort_index asc ");

		return selectByExample(ex, genreName, pageInfo);		
	}

	public static MovieItems selectInTheaterTrailers(String genreName, PagenateInfo pageInfo) {		
		Calendar calendar = Calendar.getInstance();
		QueryExample ex = new QueryExample();
		ex.or().addCriterion("movie.website=", SiteConstants.WEBSITE_MOVIEFONE)
				.addCriterion("movie.publish_time < ", calendar.getTime());
		ex.setOrderByClause("movie.publish_time desc, movie.sort_index asc ");

		return selectByExample(ex, genreName, pageInfo);		
	}

	private static MovieItems selectByExample(QueryExample ex, PagenateInfo pageInfo) {
		return selectByExample(ex, null, pageInfo);
	}

	private static MovieItems selectByExample(QueryExample ex, String genres, PagenateInfo pageInfo) {
		MovieItems items = new MovieItems(pageInfo);
		RowBounds rowBounds = new RowBounds(pageInfo.getOffset(), pageInfo.getLimit());
		SqlSession session = DefaultDBHelper.getSqlSession(true);
		try {
			MovieMapper movieMapper = session.getMapper(MovieMapper.class);
			if (StringUtils.isNullOrEmpty(genres)) {
				items.setItems(movieMapper.selectByExample(ex, rowBounds));
				if (pageInfo.getPageNo() == 1) {
					items.setTotalCount(movieMapper.countByExample(ex));
				}
			} else {
				items.setItems(movieMapper.selectWithByGenre(genres, ex, rowBounds));
				if (pageInfo.getPageNo() == 1) {
					items.setTotalCount(movieMapper.countWithByGenre(genres, ex));
				}
			}
		} finally {
			session.close();
		}
		
		return items;
	}
}
